/* -------------------------------------------------------------------------- *
   TestWinUnit - Maria Blees (maria.blees@microsoft.com)

   File: FileEnumeratorTest.cpp
   Contains tests for the FileEnumerator class.  Uses InspectableFileEnumerator
   to get access to protected members.
 * -------------------------------------------------------------------------- */
#include "WinUnit.h"

#include "InspectableFileEnumerator.h"
#include "TempFile.h"

using namespace WinUnitLib;

namespace
{
    wchar_t s_testDirectoryBuffer[MAX_PATH] = L"";
    wchar_t* s_testDirectory = NULL;
}

FIXTURE(FileEnumeratorTest);

SETUP(FileEnumeratorTest)
{
    // Create temp directory
    WIN_ASSERT_WINAPI_SUCCESS(0 != ::GetTempPathW(MAX_PATH, s_testDirectoryBuffer));
    ::wcscat_s(s_testDirectoryBuffer, L"WinUnitTestDir\\");

    s_testDirectory = s_testDirectoryBuffer;
    WIN_ASSERT_WINAPI_SUCCESS(0 != ::CreateDirectoryW(s_testDirectory, NULL), _T("Delete directory %s and re-run."), s_testDirectory);
}

TEARDOWN(FileEnumeratorTest)
{
    // Delete temp directory
    wchar_t* directory = s_testDirectory;
    s_testDirectory = NULL;

    // If there's a failure here, it could mean that you didn't close
    // some handle elsewhere and could indicate a bug.  Ideally all handles
    // would be forcibly closed to ensure proper cleanup, but this is overkill
    // considering if there's a failure something needs to be fixed anyway.
    WIN_ASSERT_WINAPI_SUCCESS(0 != ::RemoveDirectoryW(directory));
}

// ---------------------------------------------------------------------------

BEGIN_TEST(FileEnumeratorConstructorSetsHandleToInvalid)
{
    InspectableFileEnumerator f(L"FakeDirectory");

    WIN_ASSERT_EQUAL(INVALID_HANDLE_VALUE, f.GetHandle());
} END_TEST

BEGIN_TEST(FileEnumeratorGetFirstReturnsNullIfDirectoryNotFound)
{
    InspectableFileEnumerator f(L"FakeDirectory");

    WIN_ASSERT_NULL(f.GetFirst());
} END_TEST

BEGIN_TEST(FileEnumeratorGetFirstOkayToBeCalledRepeatedlyIfFails)
{
    InspectableFileEnumerator f(L"FakeDirectory");

    WIN_ASSERT_NULL(f.GetFirst());
    WIN_ASSERT_NULL(f.GetFirst());
} END_TEST

BEGIN_TEST(FileEnumeratorGetNextReturnsNullIfCalledBeforeGetFirst)
{
    InspectableFileEnumerator f(L"FakeDirectory");

    WIN_ASSERT_NULL(f.GetNext());
    WIN_ASSERT_EQUAL(1, f.Logger.OutputProgramErrorLineCalled);
    WIN_TRACE("INFO: Next line should indicate that GetFirst needs to be called before GetNext.\n");
    WIN_TRACE(L"OUTPUT: %s\n", f.Logger.OutputProgramErrorLine_msg1);
} END_TEST

BEGIN_TESTF(FileEnumeratorGetFirstShouldReturnNullIfNoFilesInDirectory, FileEnumeratorTest)
{    
    InspectableFileEnumerator fileEnumerator(s_testDirectory);
    WIN_ASSERT_NULL(fileEnumerator.GetFirst());
} 
END_TESTF

BEGIN_TESTF(FileEnumeratorGetFirstShouldReturnNullIfNoFilesInDirectoryEndingWithDll, FileEnumeratorTest)
{
    // Create in directory two files with name.txt
    TempFile file1(s_testDirectory, L"foo1.txt");
    TempFile file2(s_testDirectory, L"foo2.txt");

    InspectableFileEnumerator fileEnumerator(s_testDirectory);
    WIN_ASSERT_NULL(fileEnumerator.GetFirst());
    WIN_ASSERT_EQUAL(INVALID_HANDLE_VALUE, fileEnumerator.GetHandle());
} 
END_TESTF

BEGIN_TESTF(FileEnumeratorEnumerationShouldReturnOneFileIfAllOthersHaveDifferentExtensions, FileEnumeratorTest)
{
    TempFile file1(s_testDirectory, L"foo1.txt");
    TempFile file2(s_testDirectory, L"foo2.dll");
    TempFile file3(s_testDirectory, L"foo3.txt");

    InspectableFileEnumerator f(s_testDirectory);

    WIN_ASSERT_NOT_NULL(f.GetFirst());
    WIN_ASSERT_NULL(f.GetNext());
} 
END_TESTF

BEGIN_TESTF(FileEnumeratorEnumerationShouldReturnTwoFilesIfTwoWithRightExtension, FileEnumeratorTest)
{
    TempFile file1(s_testDirectory, L"foo1.txt");
    TempFile file2(s_testDirectory, L"foo2.dll");
    TempFile file3(s_testDirectory, L"foo3.txt");
    TempFile file4(s_testDirectory, L"foo4.dll");

    InspectableFileEnumerator f(s_testDirectory);

    WIN_ASSERT_NOT_NULL(f.GetFirst());
    WIN_ASSERT_NOT_NULL(f.GetNext());
    WIN_ASSERT_NULL(f.GetNext());
} 
END_TESTF

BEGIN_TESTF(FileEnumeratorEnumerationShouldReturnSameFileIfGetFirstCalledTwice, FileEnumeratorTest)
{
    const wchar_t* fileName = L"foo1.dll";
    TempFile file1(s_testDirectory, fileName);

    InspectableFileEnumerator f(s_testDirectory);

    const wchar_t* firstFile = f.GetFirst();
    WIN_ASSERT_STRING_EQUAL(fileName, firstFile);

    const wchar_t* firstFileAgain = f.GetFirst();
    WIN_ASSERT_STRING_EQUAL(fileName, firstFileAgain);
} 
END_TESTF

